/*
 *
 *      Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: lengleng (wangiegie@gmail.com)
 *
 */

package com.example.common.security.util;


import cn.hutool.core.util.StrUtil;
import com.example.common.cache.util.RedisUtil;
import com.example.common.i18n.util.RequestUtil;
import com.example.common.i18n.util.SpringContextHolder;
import com.example.common.security.component.CustomUser;
import com.example.common.security.constants.SecurityConstants;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 安全工具类
 *
 * @author L.cm
 */
public class SecurityUtils {

	private static RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);

	private static final String STARTWITH = "bearer";
	/**
	 * 获取Authentication
	 */
	public static Authentication getAuthentication() {
		return SecurityContextHolder.getContext().getAuthentication();
	}

	/**
	 * 获取用户
	 */
	public static CustomUser getUser(Authentication authentication) {
		Object principal = authentication.getPrincipal();
		if (principal instanceof CustomUser) {
			return (CustomUser) principal;
		}
		return null;
	}

	public static String getClientId() {
		Authentication authentication = getAuthentication();
		if (authentication instanceof OAuth2Authentication) {
			OAuth2Authentication auth2Authentication = (OAuth2Authentication) authentication;
			return auth2Authentication.getOAuth2Request().getClientId();
		}
		return null;
	}

	/**
	 * 从请求头里面获取accessToken
	 *
	 * @return
	 */
	public static String getAccessToken() {
		HttpServletRequest httpServletRequest = RequestUtil.getRequest();
		String authorization = httpServletRequest.getHeader("Authorization");
		if (StrUtil.isNotEmpty(authorization)) {
			return null;
		}
		if (authorization.toLowerCase().startsWith(STARTWITH)) {
			String accessToken = authorization.replace(STARTWITH, "").trim();
			return accessToken;
		}
		return null;
	}

	public static CustomUser getUserByToken(String accessToken) {

		try {
			TokenStore tokenStore = (TokenStore) SpringContextHolder.getBean(TokenStore.class);
			OAuth2AccessToken token = tokenStore.readAccessToken(accessToken.toString());
			OAuth2Authentication oAuth2Auth = tokenStore.readAuthentication(token);
			Authentication authentication = oAuth2Auth.getUserAuthentication();
			CustomUser user = null;
			if (authentication instanceof UsernamePasswordAuthenticationToken) {
				UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authentication;

				if (authenticationToken.getPrincipal() instanceof CustomUser) {
					user = (CustomUser) authenticationToken.getPrincipal();
					return user;
				}
			} else if (authentication instanceof PreAuthenticatedAuthenticationToken) {
				//刷新token方式
				PreAuthenticatedAuthenticationToken authenticationToken = (PreAuthenticatedAuthenticationToken) authentication;
				if (authenticationToken.getPrincipal() instanceof CustomUser) {
					user = (CustomUser) authenticationToken.getPrincipal();
					return user;
				}
			}
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取用户
	 */
	public static CustomUser getUser() {
		Authentication authentication = getAuthentication();
		if (authentication == null) {
			return null;
		}
		return getUser(authentication);
	}

	/**
	 * 获取用户角色信息
	 *
	 * @return 角色集合
	 */
	public static List<String> getRoles() {
		Authentication authentication = getAuthentication();
		Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

		List<String> roles = new ArrayList<>();
		authorities.stream()
			.filter(granted -> StrUtil.startWith(granted.getAuthority(), SecurityConstants.ROLE))
			.forEach(granted -> roles.add(StrUtil.removePrefix(granted.getAuthority(), SecurityConstants.ROLE)));
		return roles;
	}
}
